import ctypes

import pygame
from base_event import CEvent
from datetime import datetime

import sys

if sys.version_info >= (3, 11):
    import tomllib
else:
    import tomli as tomllib


def build_pos(x_s=0, y_s=0, x_e=0, y_e=0, sep=1, vertical=False):
    # 根据左上、右下坐标及分割数量、横竖排计算各坐标位置
    pos = []
    if sep < 1:
        sep = 1

    if vertical:
        # 竖排
        real_col = int((y_e - y_s) / sep)
        x_center = int((x_e + x_s) / 2)
        for i in range(sep):
            pos.append((x_center, int(y_s + (i + 0.5) * real_col)))
    else:
        # 横排
        real_col = int((x_e - x_s) / sep)
        y_center = int((y_e + y_s) / 2)
        for i in range(sep):
            pos.append((int(x_s + (i + 0.5) * real_col), y_center))
    return pos


def is_2d_array(arr):
    # 检查arr是否为列表，且所有元素也都是列表
    return isinstance(arr, list) and all(isinstance(sub, list) for sub in arr)


class BigScreen(CEvent):
    # 屏幕显示基础类
    # 通过配置文件控制：
    # 1.窗体标题
    # 2.是否全屏
    # 3.是否背景音乐及音乐文件路径
    # 4.背景图片路径
    # 5.真实刷新率用于控制文字刷新速度
    # 6.通过字体、字号、位置等配置信息控制内容显示
    # 控制说明：
    # esc   结束游戏
    # 左箭头   暂停音乐
    # 右箭头   继续音乐
    # 上箭头   音乐音量提高
    # 下箭头   音乐音量降低
    # 需重写on_other_key_down实现其他按键功能
    def __init__(self, toml_file="base_config.toml"):
        super().__init__()

        # 默认分辨率
        width = 800
        height = 600

        # 程序运行标志
        self._running = True
        # 游戏暂停标志
        self.game_paused = True
        # 音乐暂停标志
        self.music_paused = True

        # 主画面
        self._display_surf = None

        # 背景图
        self.bg = None
        # 背景图尺寸
        self.bg_size = None
        # 背景图与显示分辨率的缩放比，用于根据图坐标定位真实位置
        self.scale = None
        # 真实刷新率，过低会影响按键事件响应
        self.fps = 60

        pygame.init()
        try:
            with open(toml_file, "rb") as f:
                self.conf = tomllib.load(f)
            init = self.conf.get('init')
            # 真实刷新率，控制界面上文字的刷新速度
            self.real_fps = init.get('fps', 4)

            pygame.display.set_caption(init.get('name', "游戏"))

            if init.get('fullscreen', False):
                user32 = ctypes.windll.user32
                width = user32.GetSystemMetrics(0)
                height = user32.GetSystemMetrics(1)
            size = (width, height)
            self._display_surf = pygame.display.set_mode(size, pygame.HWSURFACE | pygame.DOUBLEBUF)

            bg_img = init.get('background', "assets/background.png")
            bg_src = pygame.image.load(bg_img)
            bg_size = bg_src.get_size()
            self.bg = pygame.transform.scale(bg_src, size)
            self.scale = (size[0] / bg_size[0], size[1] / bg_size[1])

            self.need_music = init.get('need_music', False)

            if self.need_music:
                music_file = init.get('music', "assets/music_game.wav")
                pygame.mixer.init()
                pygame.mixer.music.load(music_file)
                pygame.mixer.music.set_volume(0.5)
                pygame.mixer.music.play(-1)
                pygame.mixer.music.pause()
            self.draw_background()
            pygame.display.update()
            self._running = True
        except Exception as e:
            print(e)
            self._running = False
            pass

    def on_exit(self):
        self._running = False
        pass

    def on_wheel_up(self, event):
        self.music_up()
        pass

    def on_wheel_down(self, event):
        self.music_down()
        pass

    def on_key_down(self, event):
        key = event.key
        if key == pygame.K_ESCAPE:
            # 退出
            self._running = False
            return
        elif key == pygame.K_UP:
            # 音量+
            self.music_up()
            pass
        elif key == pygame.K_DOWN:
            # 音量-
            self.music_down()
            pass
        elif key == pygame.K_LEFT:
            # 音乐停
            self.music_pause()
            pass
        elif key == pygame.K_RIGHT:
            # 音乐起
            self.music_unpause()
            pass
        else:
            self.on_other_key_down(key)

    def on_other_key_down(self, key):
        # 在此实现其他按键的响应
        pass

    def music_unpause(self):
        if self.need_music and self.music_paused:
            pygame.mixer.music.unpause()
            self.music_paused = False

    def music_pause(self):
        if self.need_music and (not self.music_paused):
            pygame.mixer.music.pause()
            self.music_paused = True

    def music_up(self):
        # 音量+
        if self.need_music:
            v = pygame.mixer.music.get_volume()
            pygame.mixer.music.set_volume(min(1.0, v + 0.1))

    def music_down(self):
        # 音量-
        if self.need_music:
            v = pygame.mixer.music.get_volume()
            pygame.mixer.music.set_volume(max(0.0, v - 0.1))

    def draw_background(self):
        self._display_surf.blit(self.bg, (0, 0))
        pass

    def on_loop(self):
        pass

    def on_render(self):
        pass

    # def show_header(self):
    #     self.show_the_texts(None, self.conf['header'])
    #     pass

    def show_group_texts(self, texts=None, x_s=0, y_s=0, x_e=0, y_e=0, font="assets/fz.ttf", size=20, color=None,
                         vertical=False, sep=0):
        # 显示一组文字，横竖排均可
        if isinstance(texts, list):
            pos = build_pos(x_s, y_s, x_e, y_e, max(sep, len(texts)), vertical)
            if color is None:
                color = [129, 61, 5]
            font_name = pygame.font.Font(font, size)
            for i in range(len(texts)):
                text_obj = font_name.render(texts[i], True, color)
                text_pos = text_obj.get_rect()
                text_pos.center = (int(pos[i][0] * self.scale[0]),
                                   int(pos[i][1] * self.scale[1]))
                self._display_surf.blit(text_obj, text_pos)
        pass

    def show_the_texts(self, texts=None, conf=None):
        # 根据配置文件显示一维或二维组文字
        if (conf is None) or (not conf.get('show', False)):
            return
        if texts is None:
            texts = conf.get('texts', None)
        if texts is None:
            return
        x_s = conf.get('x_start', 0)
        y_s = conf.get('y_start', 0)
        x_e = conf.get('x_end', 0)
        y_e = conf.get('y_end', 0)
        font = conf.get('font', "assets/fz.ttf")
        sep = conf.get('sep', 1)
        size = conf.get('size', 20)
        colors = conf.get('colors', [[129, 61, 5]])
        vertical = conf.get('vertical', False)
        if is_2d_array(texts):
            rows = len(texts)
            x_sep = int((x_e - x_s) / rows)
            y_sep = int((y_e - y_s) / rows)
            for i in range(0, rows):
                if vertical:
                    self.show_group_texts(texts[i], x_s + i * x_sep, y_s, x_s + (i + 1) * x_sep,
                                          y_e, font, size, colors[i % len(colors)], vertical, sep)
                else:
                    self.show_group_texts(texts[i], x_s, y_s + i * y_sep, x_e,
                                          y_s + (i + 1) * y_sep, font, size, colors[i % len(colors)], vertical, sep)
        else:
            self.show_group_texts(texts, x_s, y_s, x_e, y_e, font, size, colors[0], vertical, sep)

    def on_cleanup(self):
        pass

    def on_execute(self):
        clock = pygame.time.Clock()
        current_fps = 0

        while self._running:
            for event in pygame.event.get():
                self.on_event(event)
            if not self.game_paused:
                now = int(datetime.now().microsecond * self.real_fps / 1000000)
                if now == current_fps:
                    current_fps = (current_fps + 1) % self.real_fps
                    self.on_loop()
                    pygame.display.update()
            self.on_render()
            clock.tick(self.fps)

        self.on_cleanup()
        pygame.quit()


if __name__ == "__main__":
    theApp = BigScreen()
    theApp.on_execute()
    # m = Matrix(3, 4)
    # m.transposition()

    # with open("base_config.toml", "rb") as f:
    #     conf = tomllib.load(f)
    #     print(conf.get('dc').get('ss'))
    pass
